<!-- 
  为什么在有vdom?
    因为操作真实dom慢，浏览器运行js快，使用js模拟真实dom(vdom)。目的可以快速响应视图更新。

  新旧vnode对比？
    目的是找到最小的差异，只更新差异。

  snabbdom源码：
    1）看任何框架的源码，只看主干和要点，不要去扣细节。
    2）源码是ts。ts的类型约束，不需要关注。

  h函数：
    1）作用：生成一个vnode。
    2）源码位置：src/h.ts  
    3）输入和输出：function h(sel:string, data:VNodeData,children:VNodeChildren):VNode;
       返回：return vnode(sel, data, children, text, undefined);

  vnode函数：
    1）作用：生成一个vnode（使用js去模拟真实dom）
    2）源码位置：src/vnode.ts
    3） 返回：return {sel, data, children, text, elm, key};
          <div><span>span</span></div> 对于div来说，<span>span</span>叫children
          <div>hello vdom</div> 对于div来说，hello vdom叫text
          children 和 text不能共存。

  patch函数：
    1）作用：将newVnode更新到oldVnode上，或将newVnode挂载到某个节点上。
       第1次调用patch是初次渲染，后面再去调用patch就是新旧vnode对比。
    2）源码位置：src/snabbdom.ts   当中有一个init函数，最后返回patch函数
    3）输入和输出：function patch(oldVnode: VNode | Element, vnode: VNode): VNode
    4）对于patch函数，需要考虑第一个参数是Vnode还是Element两种情况。

  diff:
    假如patch函数的第一个参数是vnode，就需要进行diff算法。新旧vnode都是树结构。
    如果让你找差异：
      1）先遍历tree1，两遍历tree2，找到差异，还需要排序。1000个节点，要计算出1亿次，算法复杂度O(n^3)，算法不可用。
      2）A) 只比较同一层级，不跨级比较。
         B) 如果tag不相同，直接删除重建，不会再深度比较了。目的是为了快速找到差异。
         C) tag和key，都相同，则认为是相同的节点，不再比较交，进行复用。

  
  总结：
    diff算法中，细节不是关键，如头头，尾尾...。算法的过程都不是核心。
    核心概念才是关键：h  vnode  patch  key  patchVnode(addVnodes,removeVnodes,updateChildren,key)
    细节不重要，updateChildren的过程也重要，不要深究。

    vdom有什么价值？
    答：让我们更快实现数据驱动视图，尽可能少的操作真实DOM。

  响应式的作用：
    监听data的数据变化，仅此而已。

  vdom:
    snabbdom 是一个vdom的库
    h -> vnode
    vnode -> vnode结构
    path -> 调用patchVnode
    patchVnode -> 调用addVnodes | 调用removeVnodes | updateChildren | key
 -->